package com.lifang.imgsoa.aop;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import com.leo.jackson.JsonTool;
import com.lifang.imgsoa.model.Response;
import com.lifang.imgsoa.util.Constants;
import com.lifang.imgsoa.util.SystemUtil;
import com.lifang.utils.CountHashMap;
import com.lifang.utils.StatisticsTimeMonitor;
import com.lifang.utils.StrUtils;

@Component
@Aspect
public class HouseImageAOP {

	private static final Logger logger = Logger.getLogger(HouseImageAOP.class);

	private static Map<String, Integer> appStatisticMap = new ConcurrentHashMap<String, Integer>();// 计数

	private static Map<String, StatisticsTimeMonitor> s_time_map = new ConcurrentHashMap<String, StatisticsTimeMonitor>();// 平均响应时间

	@PostConstruct
	private void init() {
		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
			public void run() {
				try {
					reload();
				} catch (RuntimeException e) {
					logger.info(StrUtils.ex2Str(e));
				}
			}
		}, 60, 60, TimeUnit.SECONDS);

	}

	private void reload() {
		for (Map.Entry<String, Integer> entry : appStatisticMap.entrySet()) {
			logger.info("appStatisticMap:" + entry.getKey() + "=" + entry.getValue());
		}
		appStatisticMap = new ConcurrentHashMap<String, Integer>();
	}

	@Around(value = "execution(* com.lifang.imgsoa.*.controller.*.*(..))")
	public void around(ProceedingJoinPoint point) throws Throwable {
		long startTime = System.currentTimeMillis();
		StatisticsTimeMonitor s_time = null;
		if (point == null) {
			logger.error("error:##################HouseImageAOP,method:around, the point is null here, please check ! ");
			return;
		}

		Object[] args = point.getArgs();
		if (args == null || args.length < 2) {
			logger.error("error:##################HouseImageAOP,method:around, the args is null or the length less 2 , please check ! ");
			return;
		}

		HttpServletRequest req = (HttpServletRequest) args[0];
//		HttpServletResponse resp = (HttpServletResponse) args[1];

		String app = req.getParameter("app");
		CountHashMap.addCount(appStatisticMap, StringUtils.isEmpty(app) ? "null" : app);

		// 调用目标对象的方法并获取返回值
		String methodName = point.getSignature().getName();

		s_time = s_time_map.get(methodName);
		if (s_time == null) {
			s_time = new StatisticsTimeMonitor(methodName);
			s_time_map.put(methodName, s_time);
		}

//		Object targetMethodReturnValue = 
		point.proceed(point.getArgs());

		long endTime = System.currentTimeMillis();
		s_time.exeNormal(endTime - startTime);
	}

	@AfterThrowing(value = "execution(* com.lifang.imgsoa.*.controller.*.*(..))", throwing = "e")
	public void exceptionIntercept(JoinPoint point, Throwable e) {
		if (point == null) {
			logger.error("error:##################HouseImageAOP,method:exceptionIntercept, the point is null here, please check ! ");
			return;
		}

		Object[] args = point.getArgs();
		if (args == null || args.length < 2) {
			logger.error("error:##################HouseImageAOP,method:exceptionIntercept, the args is null or the length less 2 , please check ! ");
			return;
		}
		HttpServletRequest req = (HttpServletRequest) args[0];
		HttpServletResponse resp = (HttpServletResponse) args[1];

		if ("com.lifang.imgsoa.aop.BusinessException".equals(e.getClass().getName())) {
			logger.info("BusinessException in " + point.getTarget().getClass().getName() + "." + point.getSignature().getName() + " \n " + ((BusinessException) e).getStatus() + ":" + ((BusinessException) e).getMessage());
		} else {
			logger.info("Exception in " + point.getTarget().getClass().getName() + "." + point.getSignature().getName() + " " + e.getMessage(), e);
		}
		
		this.writeError(req, resp, e);
	}

	private void writeError(HttpServletRequest req, HttpServletResponse resp, Throwable e) {
		Response html = new Response();
		if ("com.lifang.imgsoa.aop.BusinessException".equals(e.getClass().getName())) {
			html.setStatus(((BusinessException) e).getStatus());
			html.setMsg(((BusinessException) e).getMessage());
		} else {
			html.setStatus(Constants.接口异常);
			html.setMsg("网络异常请稍后重试");
		}

		SystemUtil.writeResponse(req, resp, JsonTool.writeValueAsString(html));
	}
	
	
}
